﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Text;
using PSLib.CodeFormating.Lexems;

namespace LuaLanguage
{
    [Export(typeof(ITaggerProvider))]
    [ContentType("LuaLanguageExtension")]
    [TagType(typeof(LuaTokenTag))]
    internal sealed class LuaTokenTagProvider : ITaggerProvider
    {

        public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
        {
            return new LuaTokenTagger(buffer) as ITagger<T>;
        }
    }

    public class LuaTokenTag : ITag
    {
        public Lexem Lexem { get; private set; }

        public LuaTokenTag(Lexem lexem)
        {
            this.Lexem = lexem;
        }
    }

    internal sealed class LuaTokenTagger : ITagger<LuaTokenTag>
    {
        ITextBuffer buffer;

        internal LuaTokenTagger(ITextBuffer buf)
        {
            buffer = buf;
        }

        public event EventHandler<SnapshotSpanEventArgs> TagsChanged
        {
            add { }
            remove { }
        }

        public IEnumerable<ITagSpan<LuaTokenTag>> GetTags(NormalizedSnapshotSpanCollection spans)
        {
            foreach (SnapshotSpan curSpan in spans)
            {
                ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine();
                int curLoc = containingLine.Start.Position;
                LexemList tokens = LexemParser.Parse(containingLine.GetText(), PSLib.CodeFormating.Adapters.LanguageAdapter.LuaAdaptor,false);
                foreach (var token in tokens)
                {
                    var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLoc, token.LexemSource.Length));
                    if (tokenSpan.IntersectsWith(curSpan))
                    yield return new TagSpan<LuaTokenTag>(tokenSpan,new LuaTokenTag(token));

                    //add an extra char location because of the space
                    curLoc += token.LexemSource.Length;
                }
            }
        }
    }
}
